题目描述:

小可可的学校信息组总共有n 个队员,每个人都有一个实力值a[i]。现在,一年一度的编程大赛就要到了,小可可的学校获得了若干个参赛名额,教练决定把学校信息组的n 个队员分成若干个小组去参加这场比赛。这是道类似玩斗地主的题

原题传送门->->

输入格式

输入有两行:

第一行一个正整数n,表示队员数量。
第二行有n 个整数,第i 个整数a[i]表示第i 个队员的实力。

输出格式

输出一行,包括一个正整数,表示人数最少的组的人数最大值。

输入输出样例

输入 #1

7

4 5 2 3 -4 -3 -5

输出 #1

3

说明/提示
【样例解释】 分为2 组,一组的队员实力值是{4, 5, 2, 3},一组是{-4, -3, -5}其中最小的组人数为3,可以发现没有比3 更优的分法了。

【数据范围】
对于100%的数据满足:1≤n≤10^5,∣a[i]∣≤ 10^9。

本题共10 个测试点,编号为1~10,每个测试点额外保证如下:

1~2 n≤6,1≤a[i]≤100

3~4 n ≤ 10^3 ,1≤a[i]≤ 10^5, 且a[i]互不相同

5~6 n≤ 10^5,a[i]互不相同

7~8 n≤ 10^5, 1≤a[i]≤10^5

9~10 n≤ 10^5,∣a[i]∣≤ 10^9

—————————————-分割线———————————————-

分析:大学生还在做初中组的题。。。好吧我一直知道自己是个菜鸡

分组规则:要满足递增序列,并且还要保证最小组成员数最大————俺联想到打斗地主里面的连对。问题转化为:手里有一堆牌,怎样才能组成合适的连对?

比如:五张牌:3、4、5、6、7,可以凑成连对,所以最基本的首先要找递增序列。

但是找递增序列显然不能盲目,
假如你手里牌是:

3、4、5、6、7、7、8、9、10、J(J就是11)。怎么出牌比较好呢?
答案应该是:3、4、5、6、7和7、8、9、10、J。
这道题的贪心核心就在这里:当发现有相同的数字时,要在合适的地方拆解。

再举个例子:3,4,5,6,7,7,8,8,9,9,10,J
应该分成:3,4,5,6,7,8,9以及7,8,9,10,J

其实就是在从n张到n-1张过渡的地方截取。

我是用map来存储的,第一个值为实力值,第二个值是频次。比如有3人实力为8,那么这个结点就是<8,3>,当某个小组需要一名实力为8的成员,这个结点就变成<8,2>, 直到降为<8,0>后把这个结点删除。

#include<map>
#include<iostream>
using namespace std;

map<int,int> Stu;//实力值,频次
void Input()
{
    int n;
    cin >> n;
    for(int i = 0; i < n; ++i)
    {
        int a;
        cin >> a;
        pair<map<int,int>::iterator,int> flag = Stu.insert(pair<int,int>(a,1));
        if(!flag.second)
            ++(flag.first->second);
    }
}

void solve()
{
    int ans = (1 << 30);
    while(!Stu.empty())
    {
        int tmp = 1;//tmp记录小组长度
        map<int,int>::iterator i = Stu.begin();
        pair<int,int>pre = *i;
        --(i->second);
        if(!i->second)
            i = Stu.erase(i);
        else
            ++i;
        while(i != Stu.end())
        {
            if(i->first != ( pre.first + 1))
                break;
            if(i->second == (pre.second-1))
                break;
            pre = *i;
            ++tmp;
            --(i->second);
            if(!i->second)
            i = Stu.erase(i);
            else
            ++i;
        }
        if(tmp < ans)
            ans = tmp;
    }
    cout << ans << endl;
}

int main()
{
    Input();
    solve();
    return 0;
}